package com.tx.admin.core.anno.aop;

import java.lang.reflect.Method;

import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.subject.Subject;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;

import com.tx.admin.core.controller.SuperController;
import com.tx.admin.core.anno.Rbac;
import com.tx.admin.core.anno.RbacMapping;
import com.tx.admin.modules.base.entity.RbacEntity;
import com.tx.admin.core.po.EntityPo;
import com.tx.admin.security.service.SecurityService;
import com.tx.admin.util.common.GenericUtil;
import com.tx.admin.util.common.ReflectionUtils;
import com.tx.admin.util.common.SystemUtil;
import com.tx.admin.util.web.SessionUtil;

import lombok.extern.slf4j.Slf4j;

@Component
@Aspect
@Slf4j
public class RbacMappingAop {

	
	@Autowired
	private SecurityService securityService;
	
	@Pointcut("@annotation(com.tx.admin.core.anno.RbacMapping)")
	public void aop() {
			
	}
	
	
	
	@Around("aop()")  
	public Object doAroundAdvice(ProceedingJoinPoint pjp) throws Throwable{  
		  Class<?> clazz = pjp.getTarget().getClass();
		  Rbac rbac =  AnnotationUtils.findAnnotation(clazz, Rbac.class);
		  Subject subject = SessionUtil.getSubject();
		  MethodSignature ms = (MethodSignature) pjp.getSignature();
          Method method = ms.getMethod();
          RbacMapping rbacMapping = AnnotationUtils.findAnnotation(method, RbacMapping.class);
     	  if(rbac == null || rbacMapping == null) {
     		 return pjp.proceed();
     	  }
          if(SystemUtil.isOpenDataFunction() && rbac.dataFunciton()) {
        	
        	  String permisison = rbac.value()+"-"+ rbacMapping.value();
        	  log.info("检查函数权限："+permisison);
        	  if(!subject.isPermitted(permisison)) {
        		  throw new AuthorizationException("缺少权限:"+permisison);
        	  }
        
          }
          
         Class<?> entityClass =  GenericUtil.getGeneric(clazz, SuperController.class, 0);
    
         if(rbac.dataPermisson() && RbacEntity.class.isAssignableFrom(entityClass)) {
       	  	for(Object arg:pjp.getArgs()) {
       	  	
    		  if(arg instanceof EntityPo) {
    		
    			  EntityPo<?> po =(EntityPo) arg;
    			  Object val = po.getEntity();
    			  if(val == null) {
    				  val =entityClass.newInstance();
    				  ReflectionUtils.invokeSetter(arg, "entity", val);
    			  }
    			  if(val instanceof RbacEntity) {
    				  log.info("初始化rbac实体：");
    				  RbacEntity e =(RbacEntity) val;
    				  if(rbacMapping.save()) {

    					  //修改参数限制
    					  this.securityService.saveRbacEntity(e,rbac,rbacMapping);	
    				  }else {
    					  //查询参数限制
    					  this.securityService.queryRbacEntity(e,rbac,rbacMapping);
    				  }
    			 }
    		  }
       	  	}
         }
        
		return pjp.proceed();
	}
	  
}
